#include "common.h"
#include "socket.h"
#include "message.h"
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
using namespace std;

//CipherMessage
int32_t CipherMessage::getRaw() const
{
		return raw;
}

CipherMessage::~CipherMessage() 
{

}

const Serialization CipherMessage::getSerialization() const
{
	char *ptr = (char*)&raw;
	Serialization sl( ptr, 32 );
	return sl;
}

CipherMessage* CipherMessage::fromRaw(Serialization s) 
{
	return new CipherMessage( *( (int32_t*)s.getData() ) );
}

//Message
Message::~Message()
{

}

int32_t Message::getData() const
{
	return raw;
}

const Serialization Message::getSerialization() const 
{
	char *ptr = (char*)&raw;
	Serialization sl( ptr, 32 );
	return sl;
}

Message* Message::fromRandom() 
{
	srand( (unsigned)time( NULL ) );
	int32_t temp = rand() % 256;
	temp = ( temp << 8 ) + rand() % 256;
	temp = ( temp << 8 ) + rand() % 256;
	return new Message( temp );
}

Message* Message::fromString( char* str )
{
	char flag = *str;
	int32_t temp = (int)flag;
	flag = *( str + 1 );
	temp = ( temp << 8 ) + (int)flag;
	flag = *( str + 2 );
	temp = ( temp << 8 ) + (int)flag;
	return new Message( temp );
}

Message* Message::fromRaw(Serialization s) 
{
	int32_t temp = *( (int32_t*)s.getData() );
	return new Message( temp );
}


//MessageCollection
MessageCollection::MessageCollection( uint32_t sz ) 
{
	size = sz;
	raw = new int32_t[sz];
	for (uint32_t i=0; i<sz; i++)
		raw[ i ] = 0;
}

MessageCollection::MessageCollection( uint32_t sz, int32_t* rr )
{
	size = sz;
	raw = new int32_t[sz];
	for (uint32_t i = 0; i<sz; i++)
		raw[i] = rr[i];
}

MessageCollection::~MessageCollection() 
{
	delete [] raw;
}

const Message* MessageCollection::get( const uint32_t n ) const
{
	int32_t temp = raw[ n ];	
	const Message* msg = new Message( temp );
	return msg;
}

void MessageCollection::set( const uint32_t n, const Message* msg ) 
{
	Message msg2 = *msg;
	raw[ n ] = msg2.getData();
}

uint32_t MessageCollection::getSize() const
{
	return size;
}

const Serialization MessageCollection::getSerialization() const 
{
	char *colPtr = new char[4*size+4];
	*((uint32_t*)colPtr) = size;
	for (int i=0; i<(int)size; i++ ) {
		*((int32_t*)(colPtr)+i+1) = raw[i];
	}
	Serialization sl(colPtr, 4*size+4);
	return sl;
}

MessageCollection* MessageCollection::fromRandom( uint32_t n )
{
	srand( (unsigned)time( NULL ) );
	int32_t *temp = new int32_t[ n ];
	for ( int i = 0; i < (int)n; i++ )
	{
		temp[ i ] = rand() % 256;
		temp[ i ] = ( temp[ i ] << 8 ) + rand() % 256;
		temp[ i ] = ( temp[ i ] << 8 ) + rand() % 256;		
	}
	MessageCollection* msgCol = new MessageCollection( n, temp );
	delete[] temp;
	return msgCol;
}

MessageCollection* MessageCollection::fromFile( char* path ) 
{
	ifstream fin( path );
	int32_t *temp = new int32_t[100000];
	char abc = 0;
	int index = 0;
	while( 1 ) {
		if (fin >> abc) {
			temp[index ] = (int)abc;
		}
		else {
			break;
		}
		if ( fin >> abc ) {
			temp[ index ] <<= 8;
			temp[ index ] += (int)abc;
		}
		else {
			temp[ index ] <<= 8;
		}
		if ( fin >> abc ) {
			temp[ index ] <<= 8;
			temp[ index ] += (int)abc;
		}
		else {
			temp[ index ] <<= 8;
		}
		index ++;
	};
	MessageCollection* msgCol = new MessageCollection( index, temp );
	delete[] temp;
	return msgCol;
}

MessageCollection* MessageCollection::fromRaw(Serialization s) 
{
	char *colPtr = s.getData();
	int32_t colSize = *((uint32_t*)colPtr);
	MessageCollection* msgCol = new MessageCollection(colSize);
	for ( int i = 0; i < colSize; i++ ) {
		msgCol->set(i,new Message( *((int32_t*)(colPtr)+i+1) ));
	}
	return msgCol;
}


//CipherMessageCollection
CipherMessageCollection::~CipherMessageCollection() 
{
	delete col;
}

const CipherMessage* CipherMessageCollection::get(const uint32_t n)
{
	return (CipherMessage*) col->get(n);
}

uint32_t CipherMessageCollection::getSize() const 
{
	return col->getSize();
}

const Serialization CipherMessageCollection::getSerialization() const
{
	return col->getSerialization();
}

CipherMessageCollection*  CipherMessageCollection::fromRaw(Serialization s)
{
	return new CipherMessageCollection(MessageCollection::fromRaw(s));
}